package demo;

import de.d3fact.common.events.Event;
import de.d3fact.common.events.IListener;
import de.d3fact.mfslib.processor.Processor;
import de.d3fact.mfslib.sink.Sink;
import de.d3fact.mfslib.source.Source;
import de.d3fact.mfsmodel.TokenTypeConfig;
import de.d3fact.modelapi.Model;
import de.d3fact.modelapi.dataport.IDataport;
import de.d3fact.modelapi.dataport.pull.LongPullInputport;
import de.d3fact.modelapi.scheduler.Scheduler;

public class PDemo
{

	public static final int MATERIAL_LOG = 1;
	public static final int MATERIAL_PLANK = 2;
	public static final int MATERIAL_SAWDUST = 3;

	private static int log_count = 0;
	private static int dusk_count = 0;
	private static int plank_count = 0;

	public static void main(String[] args)
	{

		IListener listener_log = new IListener()
			{

				@Override
				public void handleEvent(Event e)
				{
					log_count++;
				}

			};

		IListener listener_plank = new IListener()
			{

				@Override
				public void handleEvent(Event e)
				{
					plank_count++;
				}

			};

		IListener listener_dusk = new IListener()
			{

				@Override
				public void handleEvent(Event e)
				{
					dusk_count++;
				}

			};

		Scheduler scheduler = new Scheduler();

		Model model = new Model(scheduler);

		Source source = new Source("Source", model);
		Processor machine = new Processor("Processor", model);
		Sink sink_plank = new Sink("Sink_Plank", model);
		Sink sink_dust = new Sink("Sink_Dust", model);

		machine.getInputChannels()[0].connectTo(source.getOutputChannels()[0]);
		sink_plank.getInputChannels()[0].connectTo(machine.getOutputChannels()[0]);
		sink_dust.getInputChannels()[0].connectTo(machine.getOutputChannels()[0]);

		TokenTypeConfig log_1 = new TokenTypeConfig(MATERIAL_LOG, 1);
		TokenTypeConfig plank_1 = new TokenTypeConfig(MATERIAL_PLANK, 1);
		TokenTypeConfig dust_200 = new TokenTypeConfig(MATERIAL_SAWDUST, 200);

		TokenTypeConfig machine_output = new TokenTypeConfig();
		machine_output.setTokenType(MATERIAL_PLANK, 3);
		machine_output.setTokenType(MATERIAL_SAWDUST, 1000);

		source.<LongPullInputport> getPort(Source.DATAPORT_FREQUENCY, IDataport.DIRECTION_INPUT).directValue(100);
		machine.<LongPullInputport> getPort(Processor.DATAPORT_PROCESSING_TIME, IDataport.DIRECTION_INPUT).directValue(200);

		source.getOutputChannels()[0].configure(log_1);
		machine.getInputChannels()[0].configure(log_1);
		machine.getOutputChannels()[0].configure(machine_output);
		sink_plank.getInputChannels()[0].configure(plank_1);
		sink_dust.getInputChannels()[0].configure(dust_200);

		machine.getInputChannels()[0].addListener(IDataport.EVENT_INFORMATION_THROUGHPUT, listener_log);
		sink_dust.getInputChannels()[0].addListener(IDataport.EVENT_INFORMATION_THROUGHPUT, listener_dusk);
		sink_plank.getInputChannels()[0].addListener(IDataport.EVENT_INFORMATION_THROUGHPUT, listener_plank);

		scheduler.setStartTime(0);
		scheduler.setEndTime(1000 * 60 * 60);

		long start = System.currentTimeMillis();
		while (scheduler.currentTime() < scheduler.getEndTime() && scheduler.eventCount() > 0)
		{
			scheduler.nextStep();
		}
		System.out.println("Needed time: " + (System.currentTimeMillis() - start) + "ms");
		System.out.println("### Input ###\nLog: " + log_count);
		System.out.println("### Output ###\nPlank: " + plank_count);
		System.out.println("Dusk: " + dusk_count);
	}

}
